Skip to content

feat: animations, transitions, and UI enhancements - #24

Merged
Smartlify07 merged 25 commits into
mainfrom
feat/animations-transitions
Jul 1, 2026
Merged

feat: animations, transitions, and UI enhancements#24
Smartlify07 merged 25 commits into
mainfrom
feat/animations-transitions

Conversation

@Smartlify07

@Smartlify07 Smartlify07 commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • Scroll-into-view scale animation on hero image (motion)
  • Smooth gradient overlay transitions on navbar, hero, and course detail buttons
  • Arrow rotation on hover for multiple buttons
  • Accordion FAQ with expand/collapse and 360° plus spin
  • Horizontal expand/shrink on bridging the gap cards
  • Testimonials: scroll-to-end on button click, overflow clipping
  • Course cards: muted hover background
  • Gradient border on enroll button (before pseudo-element, hover only)
  • Join button in footer: scale up, gradient, arrow rotation

Summary by CodeRabbit

  • New Features
    • Added interactive FAQ expand/collapse with question-and-answer disclosure.
    • Enhanced hero and marketing CTAs with motion-driven entrance/hover effects, including rotating icons and glow overlays.
  • Bug Fixes
    • Improved testimonials horizontal scrolling to reliably move to the start/end.
    • Refined course details presentation with week-by-week module topics and a smoother, custom accordion interaction.
    • Updated course, navbar, footer, contact, and donation CTAs for consistent hover and responsive behavior.
  • Chores
    • Added the motion dependency for animation support.

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
modern-advocates Canceled Canceled Jul 31, 2026 9:33am

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a6cf5ec-f2e7-442c-b747-e915c638f2c1

📥 Commits

Reviewing files that changed from the base of the PR and between 91f17c9 and dedee60.

📒 Files selected for processing (2)
  • src/features/marketing/components/mission-sections.tsx
  • src/features/marketing/components/testimonials.tsx

📝 Walkthrough

Walkthrough

This PR adds motion and updates marketing UI behavior: animated hero imagery, interactive FAQ and mission sections, revised course detail content, grouped hover CTAs, and updated testimonials scrolling.

Changes

Marketing UI Interaction Updates

Layer / File(s) Summary
Motion dependency and hero animation
package.json, src/features/marketing/components/hero-section.tsx
Adds motion, converts the hero to a client component, updates the hero CTA, and animates the hero image on viewport entry.
Grouped CTA hover styling
src/features/marketing/components/course-detail-hero-section.tsx, src/features/marketing/components/courses-hero-section.tsx, src/features/marketing/components/navbar.tsx, src/features/marketing/components/contact-hero-section.tsx, src/features/marketing/components/donation-support-section.tsx, src/features/marketing/components/footer.tsx, src/features/marketing/components/cta-section.tsx, src/features/marketing/components/course-detail-content-section.tsx
CTA links and buttons gain grouped hover states, gradient overlays, and rotating arrow icons across the marketing pages.
FAQ accordion and mission hover panels
src/features/marketing/components/faq.tsx, src/features/marketing/components/mission-sections.tsx
FAQ becomes an interactive accordion, and the mission bridge section uses hover state to drive its panel layout and image transitions.
Course detail content updates
src/features/marketing/components/course-detail-content-section.tsx
Course module content expands with week topics, the accordion is rewritten with state, and review/card layout classes are adjusted.
Testimonials scroll behavior
src/features/marketing/components/testimonials.tsx
Testimonials scrolling switches to absolute targets with scrollTo, and the scroller container overflow behavior changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A bunny hopped through motion light,
With arrows spinning left and right,
FAQ blooms, the mission sways,
Course cards shimmer in hover haze,
🐇✨ soft scrolls and glows make marketing bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s main focus on UI animations, transitions, and polish across multiple components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/animations-transitions

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (4)
src/features/marketing/components/faq.tsx (1)

68-94: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add ARIA attributes for accordion accessibility.

The trigger button and answer panel lack aria-expanded, aria-controls/id linkage, and the panel lacks role="region". Screen readers can't determine the expanded/collapsed state or the relationship between trigger and content.

♿ Proposed fix
               <button
                 type="button"
                 onClick={() => toggle(i)}
+                aria-expanded={openIndex === i}
+                aria-controls={`faq-panel-${i}`}
                 className="flex w-full items-start gap-4 text-left text-primary"
               >
                 ...
               </button>

               <div
+                id={`faq-panel-${i}`}
+                role="region"
                 className={`overflow-hidden transition-all duration-300 ${
                   openIndex === i ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
                 }`}
               >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/faq.tsx` around lines 68 - 94, The FAQ
accordion in the faq component is missing accessibility wiring between the
trigger and panel. Update the button in the toggle(i) block to expose the
expanded state with aria-expanded and link it to the answer panel using
aria-controls, then give the panel a stable id and role="region" so screen
readers can associate the trigger with its content. Use the existing openIndex
state and the faq item render in faq.tsx to wire these attributes consistently
for each item.
src/features/marketing/components/mission-sections.tsx (3)

87-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant sm:flex class.

flex is already applied unconditionally, so sm:flex has no effect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/mission-sections.tsx` around lines 87 - 91,
The div in MissionSections has a redundant responsive class because it already
uses flex unconditionally, so remove the extra sm:flex from the hovered section
container in mission-sections.tsx. Update the JSX for this block so the
className only keeps the non-duplicative layout classes around the div with the
onMouseEnter/onMouseLeave handlers.

7-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

hovered state distinguishes "first" from null, but no rendering branch uses that distinction.

All three conditional styles (gridTemplateColumns at line 46, image width at line 73, image width at line 111) only check hovered === "second"; "first" and null always produce the same output. Tracking three states instead of a boolean (isSecondHovered) adds unnecessary complexity for no behavioral gain.

Suggested simplification
-  const [hovered, setHovered] = useState<"first" | "second" | null>(null)
+  const [isSecondHovered, setIsSecondHovered] = useState(false)

Then replace hovered === "second" checks with isSecondHovered, and the onMouseEnter/onMouseLeave handlers with setIsSecondHovered(true/false) accordingly.

Also applies to: 46-46, 73-73, 111-111

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/mission-sections.tsx` around lines 7 - 9,
Simplify MissionBridgeSection by replacing the unused three-state hovered union
with a boolean state like isSecondHovered. Update the state declaration in
MissionBridgeSection, then change all conditional branches that currently check
hovered === "second" to use the boolean directly for gridTemplateColumns and
both image width styles. Also replace the onMouseEnter/onMouseLeave handlers so
they set true/false instead of "first"/"second", and remove any remaining unused
distinction for "first" versus null.

70-84: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated width/height literals and wrapper structure between the two image containers.

Both panels repeat width={292}/height={318} and an almost identical wrapper class string. A small helper (e.g. <ExpandableImage src=... expanded={...} />) would remove the duplication and make future width/height adjustments single-sourced.

Also applies to: 108-122

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/mission-sections.tsx` around lines 70 - 84,
The two image blocks in mission-sections.tsx duplicate the same wrapper logic
and fixed dimensions, so extract the shared markup into a reusable component or
helper such as ExpandableImage and pass src/alt/hover state into it. Centralize
the repeated wrapper className and the width/height values there so both panels
share one source of truth and future size changes only need to be made once.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 218-230: The hover border gradient on the Link inside
CourseDetailContentSection uses an outdated Tailwind utility, so the gradient
won’t render in v4. Update the pseudo-element styling on the signup CTA to use
the Tailwind v4 linear gradient utility instead of before:bg-gradient-to-r,
keeping the rest of the Link/Button composition and class names in
course-detail-content-section.tsx unchanged.

In `@src/features/marketing/components/course-detail-hero-section.tsx`:
- Around line 80-91: The hover glow overlay in the course detail hero CTA is
using a deprecated Tailwind gradient class, so update the gradient background on
the Link’s overlay element inside course-detail-hero-section.tsx from the old
bg-gradient-to-r pattern to the Tailwind v4 bg-linear-to-r equivalent; keep the
same from/to color stops and leave the Button, Link, and ArrowRight structure
unchanged.

In `@src/features/marketing/components/footer.tsx`:
- Around line 81-84: The submit button in the footer form is scaling too
aggressively on hover and can overflow the pill container. Update the button
styles in footer.tsx so the hover effect in the submit button uses a more subtle
scale or a non-overlapping interaction, and make sure the surrounding form row
can accommodate the animation without encroaching on the email input. Locate
this in the footer form’s submit <button> markup and adjust the hover transform
accordingly.
- Around line 81-90: The footer form button overlay is using the old Tailwind
gradient utility and the hover scale is too aggressive for this compact layout.
Update the button in Footer’s submit markup to use the Tailwind v4
`bg-linear-to-r` utility on the gradient overlay, and reduce or remove the
`hover:scale-[1.5]` transform so the `Join` button doesn’t crowd the email field
in the form row.

In `@src/features/marketing/components/hero-section.tsx`:
- Around line 60-73: The CTA overlay in hero-section is using the old Tailwind
gradient utility, so update the Link’s gradient background on the floating
overlay to the v4 `bg-linear-to-r` equivalent. Use the existing hero-section
Link/overlay markup and replace the legacy gradient class while keeping the rest
of the CTA styling unchanged so the gradient renders correctly.

In `@src/features/marketing/components/mission-sections.tsx`:
- Around line 49-53: The hover-only expansion in the mission section panels is
hiding the second image from keyboard and touch users. Update the panel
container in mission-sections.tsx (the blocks using setHovered with
onMouseEnter/onMouseLeave, including the repeated panels) to support focus and
non-hover devices by adding onFocus/onBlur with a focusable target such as
tabIndex={0}, or by providing a hover-aware/touch fallback so the image is not
permanently collapsed when hover is unavailable.
- Around line 43-48: The hover layout in mission-sections is overriding the
responsive md grid with an unconditional inline gridTemplateColumns style, and
the width toggles are also applied at all breakpoints. Update the affected
section/component logic in mission-sections to drive the hover swap through
Tailwind classes or breakpoint-scoped conditional classes instead of inline
style, so the alternate column layout only activates at md and above. Make the
same responsive fix for the repeated panel width changes referenced in the same
component so they do not affect small screens.

In `@src/features/marketing/components/navbar.tsx`:
- Around line 49-64: The CTA overlay in this Navbar button still uses the
Tailwind v3 gradient utility, so update the overlay class in this Button/Link
CTA to the v4 equivalent and apply the same change to the mobile CTA below.
Locate the gradient overlay divs inside the navbar component and replace the old
gradient direction utility with bg-linear-to-r so both CTA backgrounds render
correctly.
- Around line 104-120: The mobile Consultation CTA in navbar should be aligned
with the Tailwind v4 button styles used elsewhere. Update the gradient utility
on the Link background in the mobile Button/Link block from the old directional
class to the Tailwind v4 linear variant, and keep the ArrowRight hover transform
consistent with the desktop CTA by using the negative 30deg rotation in the same
className.

In `@src/features/marketing/components/testimonials.tsx`:
- Line 73: The testimonials carousel container in testimonials.tsx is using
overflow-x-hidden, which prevents user-driven horizontal scrolling. Update the
scrollable wrapper in the testimonials component to keep horizontal scrolling
enabled (for example by restoring overflow-x-auto or overflow-x-scroll, with
hide-scrollbar if needed) while preserving the existing testimonial navigation
behavior in scrollReviews and the prev/next controls.
- Around line 29-36: The scrollReviews helper in testimonials.tsx is jumping
directly to the absolute start/end instead of moving one card at a time. Update
the scrollRef-based logic in scrollReviews so "next" and "previous" advance by a
single card/viewport increment relative to the current scroll position, rather
than using scrollWidth - clientWidth and 0. Keep the behavior anchored in
scrollRef.current and the scrollReviews direction argument, but compute the
target offset from the current scrollLeft so the carousel behaves as a true
stepwise previous/next control.

---

Nitpick comments:
In `@src/features/marketing/components/faq.tsx`:
- Around line 68-94: The FAQ accordion in the faq component is missing
accessibility wiring between the trigger and panel. Update the button in the
toggle(i) block to expose the expanded state with aria-expanded and link it to
the answer panel using aria-controls, then give the panel a stable id and
role="region" so screen readers can associate the trigger with its content. Use
the existing openIndex state and the faq item render in faq.tsx to wire these
attributes consistently for each item.

In `@src/features/marketing/components/mission-sections.tsx`:
- Around line 87-91: The div in MissionSections has a redundant responsive class
because it already uses flex unconditionally, so remove the extra sm:flex from
the hovered section container in mission-sections.tsx. Update the JSX for this
block so the className only keeps the non-duplicative layout classes around the
div with the onMouseEnter/onMouseLeave handlers.
- Around line 7-9: Simplify MissionBridgeSection by replacing the unused
three-state hovered union with a boolean state like isSecondHovered. Update the
state declaration in MissionBridgeSection, then change all conditional branches
that currently check hovered === "second" to use the boolean directly for
gridTemplateColumns and both image width styles. Also replace the
onMouseEnter/onMouseLeave handlers so they set true/false instead of
"first"/"second", and remove any remaining unused distinction for "first" versus
null.
- Around line 70-84: The two image blocks in mission-sections.tsx duplicate the
same wrapper logic and fixed dimensions, so extract the shared markup into a
reusable component or helper such as ExpandableImage and pass src/alt/hover
state into it. Centralize the repeated wrapper className and the width/height
values there so both panels share one source of truth and future size changes
only need to be made once.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aed05024-6c9d-40bb-9198-0984ba37aa11

📥 Commits

Reviewing files that changed from the base of the PR and between 58ae304 and 3f4290f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • package.json
  • src/features/marketing/components/course-detail-content-section.tsx
  • src/features/marketing/components/course-detail-hero-section.tsx
  • src/features/marketing/components/courses-hero-section.tsx
  • src/features/marketing/components/cta-section.tsx
  • src/features/marketing/components/faq.tsx
  • src/features/marketing/components/footer.tsx
  • src/features/marketing/components/hero-section.tsx
  • src/features/marketing/components/mission-sections.tsx
  • src/features/marketing/components/navbar.tsx
  • src/features/marketing/components/testimonials.tsx

Comment on lines 218 to 230
<Button
asChild
variant="outline"
className="mt-6 h-[53px] w-full gap-2.5 rounded-[60px] border-[#e5e7eb] bg-white px-5 py-4 text-base font-semibold text-ma-text hover:bg-[#f5f5f5]"
className="group relative mt-6 bg-transparent"
>
<Link href="/signup">
<Link
href="/signup"
className="relative isolate flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] border border-[#e5e7eb] bg-white px-5 py-4 text-base font-semibold text-ma-text transition-colors duration-300 before:absolute before:-inset-[2px] before:rounded-[60px] before:bg-gradient-to-r before:from-ma-glow-blue before:to-ma-glow-violet before:z-[-1] before:opacity-0 before:transition-opacity before:duration-300 group-hover:border-transparent group-hover:before:opacity-100"
>
Enroll Now
<ArrowRight className="size-5" aria-hidden="true" />
<ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</Link>
</Button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== package files ==\n'
git ls-files 'package.json' 'pnpm-lock.yaml' 'yarn.lock' 'package-lock.json' 'src/**/package.json' | sed -n '1,120p'

printf '\n== tailwind references ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'tailwindcss|bg-gradient-to-r|bg-linear-to-r' .

printf '\n== file under review context ==\n'
sed -n '210,235p' src/features/marketing/components/course-detail-content-section.tsx

Repository: Smartlify07/Modern-Advocates

Length of output: 6980


🌐 Web query:

Tailwind CSS v4 bg-gradient-to-r removed alias bg-linear-to-r documentation

💡 Result:

In Tailwind CSS v4, the former bg-gradient-to-* utilities have been renamed to bg-linear-to-* [1][2][3]. This was a breaking change introduced to align class names with the native CSS linear-gradient function and to make room for new gradient primitives, specifically radial and conic gradients [1][2][3]. There is no alias or legacy support for the old bg-gradient-to-* class names in v4; they have been completely replaced by the new bg-linear-* syntax [2][4]. Key points regarding this change: - Renaming: Classes like bg-gradient-to-r have become bg-linear-to-r [2][4]. - Expanded Functionality: The new naming structure accommodates additional types, such as bg-radial and bg-conic [2][3]. - Gradient Stops: The existing color stop utilities (from-, via-, to-*) remain compatible and function identically with the new linear gradient classes [2][4]. - Migration: Official documentation provides guidance on updating these classes, and automated migration tools are available to help transition existing projects from the v3 syntax to the v4 syntax [1][5]. Because these changes involve class names, they may need to be manually updated in dynamic string concatenations that automated tools might miss [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json, os, re
for p in ['package.json','pnpm-lock.yaml','yarn.lock','package-lock.json']:
    if os.path.exists(p):
        print(f'== {p} ==')
        if p.endswith('.json'):
            data=json.load(open(p))
            for k in ['dependencies','devDependencies','peerDependencies']:
                if k in data and 'tailwindcss' in data[k]:
                    print(k, data[k]['tailwindcss'])
        else:
            # show tailwind version mentions around first occurrences
            with open(p, 'r', encoding='utf-8', errors='ignore') as f:
                txt=f.read()
            for m in re.finditer(r'tailwindcss@[^:\n ]+|tailwindcss[^@\n ]*@[^:\n ]+', txt):
                print(m.group(0))
                break
PY

Repository: Smartlify07/Modern-Advocates

Length of output: 249


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Minimal, read-only checks for Tailwind version and relevant utility usage.
if [ -f package.json ]; then
  echo '== package.json =='
  cat package.json | python3 - <<'PY'
import json, sys
data=json.load(sys.stdin)
for k in ['dependencies','devDependencies','peerDependencies']:
    if k in data and 'tailwindcss' in data[k]:
        print(k, data[k]['tailwindcss'])
PY
fi

echo '== matches =='
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'bg-gradient-to-r|bg-linear-to-r|tailwindcss' .

Repository: Smartlify07/Modern-Advocates

Length of output: 906


🌐 Web query:

Tailwind CSS v4 bg-gradient-to-r alias removed bg-linear-to-r documentation "legacy class aliases"

💡 Result:

In Tailwind CSS v4, the bg-gradient-* class aliases used in v3 were removed and replaced with the bg-linear-* naming convention [1][2][3]. This change was implemented to better align Tailwind’s utility naming with native CSS functions (such as linear-gradient()) and to accommodate new gradient types, specifically bg-radial and bg-conic [2][3]. Key points regarding this change: - Renaming: Classes such as bg-gradient-to-r have been replaced by bg-linear-to-r [1][4]. - Migration: Tailwind provides an official upgrade tool, @tailwindcss/upgrade, which automatically updates legacy v3 class names (including gradient utilities) to their v4 equivalents during the migration process [1][5][6]. - Reasoning: Beyond simple renaming, v4 introduces expanded gradient capabilities, including support for arbitrary linear gradient angles (e.g., bg-linear-[125deg]) and gradient interpolation modifiers (e.g., /srgb, /oklch), which are conceptually clearer under the bg-linear-* namespace [7][2][3]. Documentation for these utilities can be found in the official Tailwind CSS background-image documentation, which lists the modern bg-linear-* utilities [8].

Citations:


🌐 Web query:

site:tailwindcss.com bg-gradient-to-r bg-linear-to-r Tailwind v4 legacy class aliases removed

💡 Result:

In Tailwind CSS v4, the class naming convention for gradients has been updated. The previous bg-gradient-* utility classes have been renamed to bg-linear-* [1][2]. Specifically, the bg-gradient-to-r class from Tailwind v3 has been replaced by bg-linear-to-r in v4 [3][1]. While v4 introduces these updated names to support expanded gradient functionality—such as linear gradient angles (e.g., bg-linear-45) and interpolation modifiers (e.g., bg-linear-to-r/oklch)—it does not necessarily imply a blanket removal of all legacy aliases in the framework's core; however, for gradients specifically, the documentation emphasizes the use of the new bg-linear-* naming convention [3][1]. You should update your codebase to use the bg-linear-* variants to benefit from the new API features and ensure consistency with v4 [1][2].

Citations:


Swap before:bg-gradient-to-r to before:bg-linear-to-r Tailwind v4 uses the bg-linear-* gradient utilities, so this hover border gradient won’t render as written.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-content-section.tsx` around
lines 218 - 230, The hover border gradient on the Link inside
CourseDetailContentSection uses an outdated Tailwind utility, so the gradient
won’t render in v4. Update the pseudo-element styling on the signup CTA to use
the Tailwind v4 linear gradient utility instead of before:bg-gradient-to-r,
keeping the rest of the Link/Button composition and class names in
course-detail-content-section.tsx unchanged.

Comment on lines 80 to 91
<Button
asChild
className="mt-3 h-[53px] w-full gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white hover:bg-ma-text/90"
className="group relative mt-3 overflow-hidden rounded-[60px]"
>
<Link href="/signup">
Enroll Now
<ArrowRight className="size-5" aria-hidden="true" />
<Link href="/signup" className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white">
<span className="relative z-10 inline-flex items-center gap-2.5">
Enroll Now
<ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
</Button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== package manifests ==\n'
git ls-files 'package.json' 'pnpm-lock.yaml' 'yarn.lock' 'package-lock.json' 'src/**/package.json' | sed 's#^`#-` #'

printf '\n== tailwind references ==\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'tailwindcss|bg-gradient-to-|bg-linear-to-' .

printf '\n== target file excerpt ==\n'
sed -n '70,100p' src/features/marketing/components/course-detail-hero-section.tsx

Repository: Smartlify07/Modern-Advocates

Length of output: 8023


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== package.json ==\n'
sed -n '1,220p' package.json

printf '\n== lockfile hits ==\n'
rg -n 'tailwindcss@|tailwindcss' pnpm-lock.yaml package-lock.json yarn.lock 2>/dev/null || true

Repository: Smartlify07/Modern-Advocates

Length of output: 5520


🌐 Web query:

Tailwind CSS v4 gradient utilities bg-gradient-to-r bg-linear-to-r documentation

💡 Result:

In Tailwind CSS v4, the gradient system has been overhauled to align with native CSS syntax, resulting in a breaking change where the former bg-gradient-to-* utilities have been replaced by bg-linear-to-* [1][2][3]. Key changes and usage in v4: 1. Renamed Utilities: The bg-gradient-to-* prefix used in v3 is removed [3]. You must now use bg-linear-to-* for linear gradients (e.g., bg-linear-to-r for a left-to-right gradient) [4][1][2]. 2. Directional and Angle Support: - Predefined cardinal and diagonal directions remain available (e.g., bg-linear-to-t, bg-linear-to-br, bg-linear-to-l) [4][5]. - You can now specify explicit angles directly using the bg-linear-* utility (e.g., bg-linear-45 for a 45-degree angle) [1][5][2]. - Arbitrary angle values are supported via square bracket syntax (e.g., bg-linear-[125deg]) [6][7]. 3. Gradient Stops: The color stop utilities (from-*, via-*, and to-*) function identically to v3 [1][3]. You combine them with the base gradient utility to define the colors and their positions (e.g., bg-linear-to-r from-indigo-500 via-purple-500 to-pink-500) [4][7][5]. 4. Interpolation Modes: Tailwind v4 defaults to oklab color interpolation, which provides smoother, more vibrant gradients compared to traditional sRGB [1][7][2]. You can override this using interpolation modifiers on the utility class, such as bg-linear-to-r/srgb, bg-linear-to-r/oklch, or bg-linear-to-r/hsl [4][7][2]. 5. Expanded Gradient Types: In addition to linear gradients, v4 introduces bg-radial and bg-conic utilities to support radial and conic gradients, respectively [1][2][3]. To migrate from v3, you can perform a search-and-replace for bg-gradient-to- with bg-linear-to- across your project [3].

Citations:


Use bg-linear-to-r for this gradient overlay. Tailwind v4 no longer emits bg-gradient-to-*, so this hover glow won’t render with bg-gradient-to-r here.

🛠️ Proposed fix
-                <div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
+                <div className="pointer-events-none absolute inset-0 rounded-[60px] bg-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Button
asChild
className="mt-3 h-[53px] w-full gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white hover:bg-ma-text/90"
className="group relative mt-3 overflow-hidden rounded-[60px]"
>
<Link href="/signup">
Enroll Now
<ArrowRight className="size-5" aria-hidden="true" />
<Link href="/signup" className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white">
<span className="relative z-10 inline-flex items-center gap-2.5">
Enroll Now
<ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
</Button>
<Button
asChild
className="group relative mt-3 overflow-hidden rounded-[60px]"
>
<Link href="/signup" className="flex h-[53px] w-full items-center justify-center gap-2.5 rounded-[60px] bg-ma-text px-5 py-4 text-base font-semibold text-white">
<span className="relative z-10 inline-flex items-center gap-2.5">
Enroll Now
<ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
</Button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-hero-section.tsx` around
lines 80 - 91, The hover glow overlay in the course detail hero CTA is using a
deprecated Tailwind gradient class, so update the gradient background on the
Link’s overlay element inside course-detail-hero-section.tsx from the old
bg-gradient-to-r pattern to the Tailwind v4 bg-linear-to-r equivalent; keep the
same from/to color stops and leave the Button, Link, and ArrowRight structure
unchanged.

Comment thread src/features/marketing/components/footer.tsx
Comment on lines 81 to 90
<button
type="submit"
className="inline-flex items-center justify-center gap-2 rounded-[60px] bg-ma-text px-[15px] py-3 text-[12.31px] font-semibold text-white transition-colors hover:bg-ma-text/90"
className="group relative inline-flex items-center justify-center gap-2 overflow-hidden rounded-[60px] bg-ma-text px-[15px] py-3 text-[12.31px] font-semibold text-white transition-transform duration-300 hover:scale-[1.5]"
>
Join
<ArrowRight className="size-[15px]" aria-hidden="true" />
<span className="relative z-10 inline-flex items-center gap-2">
Join
<ArrowRight className="size-[15px] transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== footer.tsx excerpt ==\n'
sed -n '1,180p' src/features/marketing/components/footer.tsx

printf '\n== Tailwind references ==\n'
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'tailwind|bg-gradient-to-r|bg-linear-to-r|`@tailwind`|tailwindcss' .

printf '\n== package manifests ==\n'
for f in package.json pnpm-lock.yaml yarn.lock package-lock.json; do
  if [ -f "$f" ]; then
    printf '\n-- %s --\n' "$f"
    sed -n '1,220p' "$f"
  fi
done

Repository: Smartlify07/Modern-Advocates

Length of output: 21473


🌐 Web query:

Tailwind CSS v4 gradient direction utility bg-gradient-to-r vs bg-linear-to-r official docs

💡 Result:

In Tailwind CSS v4, the bg-gradient-to-* utility family has been renamed to bg-linear-to-* [1][2]. This change was implemented to better align the utility names with the underlying native CSS linear-gradient() function and to support a broader suite of gradient types, including the new bg-radial and bg-conic utilities [1][3]. Key points regarding the transition: - Replacement: bg-linear-to-r is the canonical v4 equivalent of the legacy v3 bg-gradient-to-r [1][2]. The bg-gradient-to-* classes no longer exist in v4 [1][4]. - Functionality: Both utilities produce identical CSS output [1]. The color stop utilities (from-*, via-*, and to-*) remain unchanged and function exactly as they did in v3 [1][4]. - Enhanced Features: Tailwind v4 introduces new gradient capabilities, such as arbitrary angles (e.g., bg-linear-45) [1][3] and color interpolation modifiers (e.g., bg-linear-to-r/oklch or bg-linear-to-r/srgb) [5][3], which work seamlessly with the bg-linear-* syntax. If you are migrating a codebase, the official Tailwind CSS upgrade tool automatically handles the renaming of bg-gradient-to-* to bg-linear-to-* for statically parseable class strings [1][2].

Citations:


🏁 Script executed:

rg -n 'hover:scale-\[1\.5\]' src

Repository: Smartlify07/Modern-Advocates

Length of output: 452


Use bg-linear-to-r for this overlay. bg-gradient-to-r is the Tailwind v4 rename, so the hover gradient won’t render here. The hover:scale-[1.5] button also crowds the email field in this tight form row.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/footer.tsx` around lines 81 - 90, The
footer form button overlay is using the old Tailwind gradient utility and the
hover scale is too aggressive for this compact layout. Update the button in
Footer’s submit markup to use the Tailwind v4 `bg-linear-to-r` utility on the
gradient overlay, and reduce or remove the `hover:scale-[1.5]` transform so the
`Join` button doesn’t crowd the email field in the form row.

Comment on lines 60 to 73
<div className="mt-10 flex items-center gap-5">
<Link
href="/contact"
className="inline-flex items-center justify-center gap-1.5 rounded-[60px] bg-ma-text px-5 py-4 text-xs font-semibold text-nowrap text-white transition-colors hover:bg-ma-text/90 sm:gap-2.5 sm:text-base"
className="group relative inline-flex items-center justify-center overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 sm:gap-2.5 sm:text-base"
>
Book consultation
<ArrowRight className="size-5" aria-hidden="true" />
<span className="relative z-10 inline-flex items-center justify-center gap-1.5 text-xs font-semibold text-nowrap text-white sm:gap-2.5 sm:text-base">
Book consultation
<ArrowRight
className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]"
aria-hidden="true"
/>
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use bg-linear-to-r here. Tailwind v4 renamed the legacy bg-gradient-to-r utility, so this CTA overlay won't render as intended until it's updated.

🛠️ Proposed fix
-            <div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
+            <div className="pointer-events-none absolute inset-0 rounded-[60px] bg-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="mt-10 flex items-center gap-5">
<Link
href="/contact"
className="inline-flex items-center justify-center gap-1.5 rounded-[60px] bg-ma-text px-5 py-4 text-xs font-semibold text-nowrap text-white transition-colors hover:bg-ma-text/90 sm:gap-2.5 sm:text-base"
className="group relative inline-flex items-center justify-center overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 sm:gap-2.5 sm:text-base"
>
Book consultation
<ArrowRight className="size-5" aria-hidden="true" />
<span className="relative z-10 inline-flex items-center justify-center gap-1.5 text-xs font-semibold text-nowrap text-white sm:gap-2.5 sm:text-base">
Book consultation
<ArrowRight
className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]"
aria-hidden="true"
/>
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
<div className="mt-10 flex items-center gap-5">
<Link
href="/contact"
className="group relative inline-flex items-center justify-center overflow-hidden rounded-[60px] bg-ma-text px-5 py-4 sm:gap-2.5 sm:text-base"
>
<span className="relative z-10 inline-flex items-center justify-center gap-1.5 text-xs font-semibold text-nowrap text-white sm:gap-2.5 sm:text-base">
Book consultation
<ArrowRight
className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]"
aria-hidden="true"
/>
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-linear-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/hero-section.tsx` around lines 60 - 73, The
CTA overlay in hero-section is using the old Tailwind gradient utility, so
update the Link’s gradient background on the floating overlay to the v4
`bg-linear-to-r` equivalent. Use the existing hero-section Link/overlay markup
and replace the legacy gradient class while keeping the rest of the CTA styling
unchanged so the gradient renders correctly.

Comment on lines +49 to +53
<div
onMouseEnter={() => setHovered("first")}
onMouseLeave={() => setHovered(null)}
className="flex flex-col gap-5 rounded-2xl bg-white p-5 sm:flex-row"
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Second panel's image is gated entirely behind :hover, with no keyboard or touch fallback.

onMouseEnter/onMouseLeave are the only triggers for expanding the second image; there's no onFocus/onBlur/tabIndex equivalent, and devices without reliable hover (touch/tablet) will likely never reveal this image since it defaults to w-0. This permanently hides content for a meaningful chunk of users with no fallback path.

Consider:

  • Adding onFocus/onBlur alongside the mouse handlers and making the panel focusable (tabIndex={0}) for keyboard parity.
  • Or using @media (hover: hover) / a touch-aware fallback so the image isn't unconditionally collapsed on devices that can't hover.

Also applies to: 87-91, 108-122

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/mission-sections.tsx` around lines 49 - 53,
The hover-only expansion in the mission section panels is hiding the second
image from keyboard and touch users. Update the panel container in
mission-sections.tsx (the blocks using setHovered with
onMouseEnter/onMouseLeave, including the repeated panels) to support focus and
non-hover devices by adding onFocus/onBlur with a focusable target such as
tabIndex={0}, or by providing a hover-aware/touch fallback so the image is not
permanently collapsed when hover is unavailable.

Comment on lines 49 to 64
<Button
asChild
className="hidden h-13 w-[157px] gap-[6px] rounded-[60px] px-5 py-4 md:inline-flex"
className="group relative hidden overflow-hidden rounded-[60px] md:inline-flex"
>
<Link href="/contact">
Consultation
<ArrowRight className="size-3.5" aria-hidden="true" />
<Link
href="/contact"
className="flex h-13 w-[157px] items-center justify-center gap-[6px] rounded-[60px] px-5 py-4 text-base font-semibold"
>
<span className="relative z-10">Consultation</span>
<ArrowRight
className="relative z-10 size-5 transition-transform duration-300 group-hover:rotate-[-30deg]"
aria-hidden="true"
/>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
</Button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use bg-linear-to-r for both CTA overlays
bg-gradient-to-r is a Tailwind v3 class; in v4 this should be bg-linear-to-r, otherwise the gradient overlay won't render. The same fix applies to the mobile CTA below.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/navbar.tsx` around lines 49 - 64, The CTA
overlay in this Navbar button still uses the Tailwind v3 gradient utility, so
update the overlay class in this Button/Link CTA to the v4 equivalent and apply
the same change to the mobile CTA below. Locate the gradient overlay divs inside
the navbar component and replace the old gradient direction utility with
bg-linear-to-r so both CTA backgrounds render correctly.

Comment on lines 104 to 120
<Button
asChild
className="mt-2 h-13 w-full gap-[6px] rounded-[60px] px-5 py-4"
className="group relative mt-2 overflow-hidden rounded-[60px]"
>
<Link href="/contact" onClick={() => setMobileOpen(false)}>
Consultation
<ArrowRight className="size-3.5" aria-hidden="true" />
<Link
href="/contact"
onClick={() => setMobileOpen(false)}
className="flex h-13 w-full items-center justify-center gap-[6px] rounded-[60px] px-5 py-4"
>
<span className="relative z-10">Consultation</span>
<ArrowRight
className="relative z-10 size-3.5 transition-transform duration-300 group-hover:rotate-[30deg]"
aria-hidden="true"
/>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</Link>
</Button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== navbar snippet ==\n'
sed -n '45,130p' src/features/marketing/components/navbar.tsx

printf '\n== gradient utility search ==\n'
rg -n "bg-(gradient-to-r|linear-to-r)" src/features/marketing -g '*.tsx' -g '*.ts'

printf '\n== ArrowRight rotation search ==\n'
rg -n "rotate-\[-?30deg\]" src/features/marketing -g '*.tsx' -g '*.ts'

Repository: Smartlify07/Modern-Advocates

Length of output: 6440


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== package.json tailwind deps ==\n'
sed -n '1,220p' package.json

printf '\n== tailwind-related files ==\n'
fd -a 'tailwind*' .

printf '\n== tailwind config contents (if any) ==\n'
for f in $(fd -a 'tailwind.*(js|cjs|mjs|ts|config.*)' .); do
  echo "--- $f ---"
  sed -n '1,220p' "$f"
done

Repository: Smartlify07/Modern-Advocates

Length of output: 2351


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json, pathlib
p = pathlib.Path('package.json')
data = json.loads(p.read_text())
for key in ('dependencies','devDependencies','peerDependencies','optionalDependencies'):
    deps = data.get(key, {})
    if any('tailwind' in k.lower() for k in deps):
        print(f'[{key}]')
        for k,v in deps.items():
            if 'tailwind' in k.lower():
                print(f'{k}: {v}')
PY

Repository: Smartlify07/Modern-Advocates

Length of output: 299


🌐 Web query:

Tailwind CSS v4 directional gradient utility bg-gradient-to-r bg-linear-to-r docs migration

💡 Result:

In Tailwind CSS v4, the directional gradient utilities have been renamed from bg-gradient-to-* to bg-linear-to-* to align with the underlying CSS linear-gradient() function and to accommodate new gradient types like bg-radial and bg-conic [1][2][3]. Migration details: - Renaming: All existing v3 bg-gradient-to-* classes must be updated to bg-linear-to-* (e.g., bg-gradient-to-r becomes bg-linear-to-r) [2][4]. - Automation: The official Tailwind CSS upgrade tool (npx @tailwindcss/upgrade``) automatically detects and rewrites these class names in your project files [1][2][3][5]. - Color Stops: The color stop utilities (from-*, `via-`, `to-`) and their modifiers (positions, opacity) remain unchanged and function exactly as they did in v3 [2][4][6]. - New Features: v4 introduces expanded capabilities for linear gradients, including support for arbitrary angles (e.g., `bg-linear-45`), new color interpolation modifiers (e.g., `/srgb`, `/oklch`), and support for radial and conic gradients [2][3][7][8]. It is recommended to run the automated upgrade command to handle these changes, as manual updates may miss dynamic or concatenated class strings [2][5].

Citations:


Update the mobile Consultation CTA to match Tailwind v4 and the other CTAs
bg-gradient-to-r should be bg-linear-to-r here, and the arrow hover rotation should stay -30deg to match the desktop CTA and the rest of the marketing buttons.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/navbar.tsx` around lines 104 - 120, The
mobile Consultation CTA in navbar should be aligned with the Tailwind v4 button
styles used elsewhere. Update the gradient utility on the Link background in the
mobile Button/Link block from the old directional class to the Tailwind v4
linear variant, and keep the ArrowRight hover transform consistent with the
desktop CTA by using the negative 30deg rotation in the same className.

Comment on lines 29 to 36
function scrollReviews(direction: "previous" | "next") {
scrollRef.current?.scrollBy({
left: direction === "next" ? 360 : -360,
const el = scrollRef.current
if (!el) return
el.scrollTo({
left: direction === "next" ? el.scrollWidth - el.clientWidth : 0,
behavior: "smooth",
})
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

scrollReviews no longer steps incrementally — it jumps straight to start/end.

next always scrolls to scrollWidth - clientWidth (the absolute end) and previous always scrolls to 0 (the absolute start), regardless of current scroll position. With more than two cards visible, clicking "next" repeatedly does nothing after the first click (already at the end), and there's no way to advance through cards one at a time — the buttons effectively become a binary "jump to start/jump to end" toggle rather than a carousel previous/next control.

🔧 Possible fix: step by one card width
   function scrollReviews(direction: "previous" | "next") {
     const el = scrollRef.current
     if (!el) return
+    const cardWidth = 330 + 30 // card width + gap
     el.scrollTo({
-      left: direction === "next" ? el.scrollWidth - el.clientWidth : 0,
+      left:
+        direction === "next"
+          ? Math.min(el.scrollLeft + cardWidth, el.scrollWidth - el.clientWidth)
+          : Math.max(el.scrollLeft - cardWidth, 0),
       behavior: "smooth",
     })
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function scrollReviews(direction: "previous" | "next") {
scrollRef.current?.scrollBy({
left: direction === "next" ? 360 : -360,
const el = scrollRef.current
if (!el) return
el.scrollTo({
left: direction === "next" ? el.scrollWidth - el.clientWidth : 0,
behavior: "smooth",
})
}
function scrollReviews(direction: "previous" | "next") {
const el = scrollRef.current
if (!el) return
const cardWidth = 330 + 30 // card width + gap
el.scrollTo({
left:
direction === "next"
? Math.min(el.scrollLeft + cardWidth, el.scrollWidth - el.clientWidth)
: Math.max(el.scrollLeft - cardWidth, 0),
behavior: "smooth",
})
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/testimonials.tsx` around lines 29 - 36, The
scrollReviews helper in testimonials.tsx is jumping directly to the absolute
start/end instead of moving one card at a time. Update the scrollRef-based logic
in scrollReviews so "next" and "previous" advance by a single card/viewport
increment relative to the current scroll position, rather than using scrollWidth
- clientWidth and 0. Keep the behavior anchored in scrollRef.current and the
scrollReviews direction argument, but compute the target offset from the current
scrollLeft so the carousel behaves as a true stepwise previous/next control.

<div
ref={scrollRef}
className="hide-scrollbar mt-[86px] flex gap-[30px] overflow-x-auto scroll-smooth px-4 pb-2 xl:px-25 2xl:pl-50"
className="relative mt-[86px] flex gap-[30px] overflow-x-hidden px-4 pb-2 xl:px-25 2xl:pl-50"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

overflow-x-hidden disables user-driven scrolling (touch/trackpad/scrollbar drag).

Switching from overflow-x-auto to overflow-x-hidden means the element can still be scrolled programmatically via scrollTo, but end users can no longer swipe/drag or use a trackpad/scrollbar to browse testimonials — they're now fully dependent on the prev/next buttons. Combined with the binary start/end jump in scrollReviews above, this significantly limits how users can browse the testimonials carousel, especially on touch devices.

hide-scrollbar (referenced in src/app/globals.css) was removed since overflow-x-hidden already suppresses the scrollbar, so that part is fine — but consider keeping overflow-x-auto hide-scrollbar (or overflow-x-scroll) if touch/swipe scrolling should remain available.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/testimonials.tsx` at line 73, The
testimonials carousel container in testimonials.tsx is using overflow-x-hidden,
which prevents user-driven horizontal scrolling. Update the scrollable wrapper
in the testimonials component to keep horizontal scrolling enabled (for example
by restoring overflow-x-auto or overflow-x-scroll, with hide-scrollbar if
needed) while preserving the existing testimonial navigation behavior in
scrollReviews and the prev/next controls.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/features/marketing/components/course-detail-content-section.tsx (3)

191-206: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Fixed max-h-[500px] is a brittle animation approach.

If topic list content ever exceeds 500px it will clip abruptly, and short content still animates over the full fixed duration disproportionately. Since motion was just added to this PR's dependencies for the hero animation, using it here (e.g. AnimatePresence/motion.div with height: auto) would be more consistent and robust than the max-height hack.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-content-section.tsx` around
lines 191 - 206, The topics panel in course-detail-content-section.tsx still
uses a brittle fixed max-height transition, which can clip longer content and
animate short content poorly. Update the open/close behavior in the course
detail section to use motion-based expansion instead of the max-h-[500px] hack,
ideally with AnimatePresence and a motion.div that animates height to auto. Keep
the existing open state and topics rendering logic, but replace the
overflow/transition class approach with the new motion animation for the topics
container.

168-194: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider cn() for conditional classes instead of template-literal concatenation.

Elsewhere in the codebase (e.g., Button) conditional class composition goes through cn(); using raw template literals here is inconsistent and harder to maintain/merge safely.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-content-section.tsx` around
lines 168 - 194, The conditional class composition in the course detail
accordion should use the shared cn() helper instead of inline template-literal
concatenation. Update the wrapper, ChevronDown, and open-state container class
handling in the component that renders the title/button toggle so the
conditional styles are merged through cn(), matching the pattern used elsewhere
like Button and keeping class composition consistent and safer to extend.

319-332: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Enroll button: variant="outline" is fully overridden by the child Link's own classes — verify merge behavior.

Button renders via Radix Slot.Root when asChild is set, merging buttonVariants({variant: "outline", ...}) output into the Link. The Link here re-declares border/background/padding/height directly, which likely wins or conflicts with the outline variant depending on cn/tailwind-merge class-merge order — making the variant="outline" prop effectively dead weight, or worse, an unpredictable visual result depending on class merge order.

Simplify by dropping the redundant Button wrapper/variant if the Link already fully defines the visual style, or move all styling into the Button's className and let Link stay unstyled.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-content-section.tsx` around
lines 319 - 332, The enroll CTA styling is duplicating and conflicting between
Button’s outline variant and the nested Link classes, so the variant on Button
is effectively redundant. Update the CourseDetailContentSection enroll block to
either remove the Button/asChild wrapper and keep the Link fully styled, or move
the full styling into Button and leave Link unstyled; use Button,
ButtonVariants, and the Link inside this enroll action as the key points to
adjust.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 156-209: The custom accordion in CourseModule no longer exposes
native disclosure state, so add accessible toggle semantics to the button and
panel. Update the button in CourseModule to include aria-expanded reflecting the
open state and aria-controls pointing to the collapsible content, and give the
content container a stable id that matches it. Keep the existing open state
logic and ChevronDown rotation, but ensure the button/content pairing in
CourseModule preserves screen reader announcements for expanded/collapsed state.

In `@src/features/marketing/components/donation-support-section.tsx`:
- Line 131: The overlay in donation-support-section still uses the removed
Tailwind v3 gradient utility, so update the gradient class on the highlighted
absolute div to the Tailwind v4 equivalent. Keep the existing styling and
behavior intact, but replace bg-gradient-to-r with bg-linear-to-r so the hover
overlay renders correctly in the component.

---

Nitpick comments:
In `@src/features/marketing/components/course-detail-content-section.tsx`:
- Around line 191-206: The topics panel in course-detail-content-section.tsx
still uses a brittle fixed max-height transition, which can clip longer content
and animate short content poorly. Update the open/close behavior in the course
detail section to use motion-based expansion instead of the max-h-[500px] hack,
ideally with AnimatePresence and a motion.div that animates height to auto. Keep
the existing open state and topics rendering logic, but replace the
overflow/transition class approach with the new motion animation for the topics
container.
- Around line 168-194: The conditional class composition in the course detail
accordion should use the shared cn() helper instead of inline template-literal
concatenation. Update the wrapper, ChevronDown, and open-state container class
handling in the component that renders the title/button toggle so the
conditional styles are merged through cn(), matching the pattern used elsewhere
like Button and keeping class composition consistent and safer to extend.
- Around line 319-332: The enroll CTA styling is duplicating and conflicting
between Button’s outline variant and the nested Link classes, so the variant on
Button is effectively redundant. Update the CourseDetailContentSection enroll
block to either remove the Button/asChild wrapper and keep the Link fully
styled, or move the full styling into Button and leave Link unstyled; use
Button, ButtonVariants, and the Link inside this enroll action as the key points
to adjust.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b60dd4a3-4bdc-49b0-8907-c9d0f4ab0297

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4290f and 91f17c9.

📒 Files selected for processing (7)
  • src/features/marketing/components/contact-hero-section.tsx
  • src/features/marketing/components/course-detail-content-section.tsx
  • src/features/marketing/components/cta-section.tsx
  • src/features/marketing/components/donation-support-section.tsx
  • src/features/marketing/components/footer.tsx
  • src/features/marketing/components/hero-section.tsx
  • src/features/marketing/components/testimonials.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/features/marketing/components/footer.tsx
  • src/features/marketing/components/cta-section.tsx
  • src/features/marketing/components/testimonials.tsx
  • src/features/marketing/components/hero-section.tsx

Comment on lines 156 to 209
function CourseModule({
title,
topics,
open = false,
open: defaultOpen = false,
}: {
title: string
topics?: string[]
open?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)

return (
<details
open={open}
className="group rounded-2xl border border-[#d9d9d9] bg-white px-5 pt-[17px] pb-5 open:bg-[#f5f5f5]"
<div
className={`rounded-2xl border border-[#d9d9d9] px-5 pt-[17px] pb-5 transition-colors ${
open ? "bg-[#f5f5f5]" : "bg-white"
}`}
>
<summary className="flex cursor-pointer list-none items-center justify-between gap-4 [&::-webkit-details-marker]:hidden">
<button
type="button"
onClick={() => setOpen(!open)}
className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
>
<h3 className="text-sm/[100%] leading-normal font-bold text-ma-text sm:text-base">
{title}
</h3>
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-[15px] border border-[#d9d9d9] bg-white">
<ChevronDown
className="size-3.5 group-open:hidden"
aria-hidden="true"
/>
<ChevronUp
className="hidden size-3.5 group-open:block"
className={`size-3.5 transition-transform duration-600 ${
open ? "rotate-180" : ""
}`}
aria-hidden="true"
/>
</span>
</summary>
</button>

{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</details>
<div
className={`overflow-hidden transition-all duration-300 ${
open ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
}`}
>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</div>
</div>
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Custom accordion drops native disclosure semantics — add aria-expanded/aria-controls.

The previous <details>/<summary> implementation was natively accessible (announces expanded/collapsed state). The new <button>-driven toggle has no aria-expanded on the button and no aria-controls/id linking it to the content panel, so screen reader users get no indication of state.

♿ Proposed fix
+      <button
+        type="button"
+        onClick={() => setOpen(!open)}
+        aria-expanded={open}
+        aria-controls={`module-panel-${title}`}
+        className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
+      >
-      <button
-        type="button"
-        onClick={() => setOpen(!open)}
-        className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
-      >
@@
-      <div
+      <div
+        id={`module-panel-${title}`}
         className={`overflow-hidden transition-all duration-300 ${
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function CourseModule({
title,
topics,
open = false,
open: defaultOpen = false,
}: {
title: string
topics?: string[]
open?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)
return (
<details
open={open}
className="group rounded-2xl border border-[#d9d9d9] bg-white px-5 pt-[17px] pb-5 open:bg-[#f5f5f5]"
<div
className={`rounded-2xl border border-[#d9d9d9] px-5 pt-[17px] pb-5 transition-colors ${
open ? "bg-[#f5f5f5]" : "bg-white"
}`}
>
<summary className="flex cursor-pointer list-none items-center justify-between gap-4 [&::-webkit-details-marker]:hidden">
<button
type="button"
onClick={() => setOpen(!open)}
className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
>
<h3 className="text-sm/[100%] leading-normal font-bold text-ma-text sm:text-base">
{title}
</h3>
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-[15px] border border-[#d9d9d9] bg-white">
<ChevronDown
className="size-3.5 group-open:hidden"
aria-hidden="true"
/>
<ChevronUp
className="hidden size-3.5 group-open:block"
className={`size-3.5 transition-transform duration-600 ${
open ? "rotate-180" : ""
}`}
aria-hidden="true"
/>
</span>
</summary>
</button>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</details>
<div
className={`overflow-hidden transition-all duration-300 ${
open ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
}`}
>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</div>
</div>
)
}
function CourseModule({
title,
topics,
open: defaultOpen = false,
}: {
title: string
topics?: string[]
open?: boolean
}) {
const [open, setOpen] = useState(defaultOpen)
return (
<div
className={`rounded-2xl border border-[`#d9d9d9`] px-5 pt-[17px] pb-5 transition-colors ${
open ? "bg-[`#f5f5f5`]" : "bg-white"
}`}
>
<button
type="button"
onClick={() => setOpen(!open)}
aria-expanded={open}
aria-controls={`module-panel-${title}`}
className="flex w-full cursor-pointer items-center justify-between gap-4 text-left"
>
<h3 className="text-sm/[100%] leading-normal font-bold text-ma-text sm:text-base">
{title}
</h3>
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-[15px] border border-[`#d9d9d9`] bg-white">
<ChevronDown
className={`size-3.5 transition-transform duration-600 ${
open ? "rotate-180" : ""
}`}
aria-hidden="true"
/>
</span>
</button>
<div
id={`module-panel-${title}`}
className={`overflow-hidden transition-all duration-300 ${
open ? "max-h-[500px] opacity-100" : "max-h-0 opacity-0"
}`}
>
{topics ? (
<div className="mt-4 text-sm leading-normal text-ma-text sm:text-[15px]">
<p>Topics:</p>
<ul className="list-disc pl-5">
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
) : null}
</div>
</div>
)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/course-detail-content-section.tsx` around
lines 156 - 209, The custom accordion in CourseModule no longer exposes native
disclosure state, so add accessible toggle semantics to the button and panel.
Update the button in CourseModule to include aria-expanded reflecting the open
state and aria-controls pointing to the collapsible content, and give the
content container a stable id that matches it. Keep the existing open state
logic and ChevronDown rotation, but ensure the button/content pairing in
CourseModule preserves screen reader announcements for expanded/collapsed state.

Donate Now
<ArrowRight className="size-5 transition-transform duration-300 group-hover:rotate-[-30deg]" aria-hidden="true" />
</span>
<div className="pointer-events-none absolute inset-0 rounded-[60px] bg-gradient-to-r from-ma-glow-blue to-ma-glow-violet opacity-0 transition-opacity duration-500 group-hover:opacity-100" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Tailwind-related files =="
git ls-files | rg 'tailwind|postcss|css$|package.json$|donut|marketing/components/(donation-support-section|contact-form-button)'

echo
echo "== Search for gradient utilities =="
rg -n --hidden --no-ignore-vcs 'bg-gradient-to-r|bg-linear-to-r|tailwind' src . -g '!node_modules' -g '!dist' -g '!build'

echo
echo "== Inspect package.json and Tailwind config files =="
for f in package.json tailwind.config.* postcss.config.* src/**/*.css src/**/*.tsx; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    sed -n '1,220p' "$f"
  fi
done

Repository: Smartlify07/Modern-Advocates

Length of output: 19289


🌐 Web query:

Tailwind CSS v4 bg-gradient-to-r bg-linear-to-r renamed gradient utilities alias removed

💡 Result:

In Tailwind CSS v4, the bg-gradient-to-* utilities have been replaced by bg-linear-to-* to better align with the underlying CSS linear-gradient() function [1][2]. Key changes in v4 include: 1. Renaming: All linear gradient utilities have been renamed from bg-gradient-to-* to bg-linear-to-* (e.g., bg-gradient-to-r becomes bg-linear-to-r) [1][3]. The legacy bg-gradient-* alias has been removed in the v4 release [1][3]. 2. Expanded API: In addition to the standard directional utilities (like bg-linear-to-r or bg-linear-to-tl), v4 introduces support for explicit angles (e.g., bg-linear-45) and arbitrary values (e.g., bg-linear-[125deg]) [1][4][2]. 3. Consistency: These changes are part of a broader expansion of gradient utilities, which now also include bg-radial and bg-conic [1][2]. 4. Functionality: The associated color stop utilities—from-*, via-*, and to-*—remain functionally identical to their v3 counterparts [1][3]. Additionally, v4 introduces modifiers for color interpolation (e.g., /srgb, /oklch), which can be appended to the gradient utility [5][2]. For those migrating from v3, replacing the bg-gradient-to- prefix with bg-linear-to- is required, as the old class names are no longer supported [1][3].

Citations:


Use bg-linear-to-r here. This overlay still uses the removed v3 bg-gradient-to-r utility, so the gradient won’t apply in Tailwind v4.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/marketing/components/donation-support-section.tsx` at line 131,
The overlay in donation-support-section still uses the removed Tailwind v3
gradient utility, so update the gradient class on the highlighted absolute div
to the Tailwind v4 equivalent. Keep the existing styling and behavior intact,
but replace bg-gradient-to-r with bg-linear-to-r so the hover overlay renders
correctly in the component.

@Smartlify07
Smartlify07 merged commit c5d20f3 into main Jul 1, 2026
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant